import numpy as np
import trimesh
import meshpy.tet as tet
from .mesh_quality import evaluate_mesh_quality


class GeometryCreator:
    """几何体创建类"""

    @staticmethod
    def create_slope(S1: float = 8.0, S2: float = 12.0, H1: float = 2.0, H2: float = 1.0,
                     C: float = 12.0, width: float = 5.0, alpha: float = 45.0,
                     subdivisions: int = 3) -> tuple[trimesh.Trimesh, float, float]:
        """创建路堤边坡（整体几何体：底部长方体与上部梯形台无缝连接）"""
        try:
            print("1. 开始计算几何参数...")
            # 计算上部边坡参数
            alpha_rad = np.deg2rad(alpha)  # 角度转弧度
            L = H1 / np.tan(alpha_rad)  # 水平投影长度
            print(f"   计算完成: L={L:.2f}m")

            print("\n2. 开始创建顶点...")
            # 使用用户输入的S1和S2参数
            B = S1  # 梯形台顶部长度（上底边）
            b = S2  # 梯形台底部长度（下底边）

            # 验证梯形台长度小于长方体长度
            print(f"   参数验证:")
            print(f"   - 长方体长度(C): {C:.2f}m")
            print(f"   - 梯形台顶部长度(S1): {S1:.2f}m")
            print(f"   - 梯形台底部长度(S2): {S2:.2f}m")
            print(f"   - 水平投影长度(L): {L:.2f}m")

            # 确保梯形台底部长度小于长方体长度
            if S2 >= C:
                raise ValueError(f"梯形台底部长度({S2:.2f}m)大于等于长方体长度({C}m)，请调整参数")

            # 确保梯形台顶部长度小于长方体长度
            if S1 >= C:
                raise ValueError(f"梯形台顶部长度({S1:.2f}m)大于等于长方体长度({C}m)，请调整参数")

            print(f"   ✓ 验证通过：梯形台长度小于长方体长度")

            # 计算顶点坐标 - 重新设计为整体几何体
            vertices = np.array([
                # 底面（整体底面）
                [0, 0, 0],  # 0: 左前底点
                [C, 0, 0],  # 1: 右前底点
                [C, width, 0],  # 2: 右后底点
                [0, width, 0],  # 3: 左后底点

                # 中间层（长方体顶部，与梯形台底部重合）
                [0, 0, H2],  # 4: 左前中点
                [C, 0, H2],  # 5: 右前中点
                [C, width, H2],  # 6: 右后中点
                [0, width, H2],  # 7: 左后中点

                # 梯形台底部（与长方体顶部重合）
                [(C - S2) / 2, 0, H2],  # 8: 左前梯形底点
                [(C + S2) / 2, 0, H2],  # 9: 右前梯形底点
                [(C + S2) / 2, width, H2],  # 10: 右后梯形底点
                [(C - S2) / 2, width, H2],  # 11: 左后梯形底点

                # 顶部（梯形台顶部）
                [(C - S1) / 2, 0, H1 + H2],  # 12: 左前顶点
                [(C + S1) / 2, 0, H1 + H2],  # 13: 右前顶点
                [(C + S1) / 2, width, H1 + H2],  # 14: 右后顶点
                [(C - S1) / 2, width, H1 + H2]  # 15: 左后顶点
            ])
            print(f"   创建了 {len(vertices)} 个顶点")

            print("\n3. 开始创建面片...")
            # 定义面片（三角形）- 重新设计为整体几何体
            faces = np.array([
                # 底面（整体底面）
                [0, 2, 1], [0, 3, 2],

                # 前面（整体前面，包含长方体和梯形台）
                [0, 1, 4], [1, 5, 4],  # 长方体前面
                [4, 5, 8], [5, 9, 8],  # 长方体顶部到梯形台底部
                [8, 9, 12], [9, 13, 12],  # 梯形台前面

                # 右面（整体右面）
                [1, 2, 5], [2, 6, 5],  # 长方体右面
                [5, 6, 9], [6, 10, 9],  # 长方体顶部到梯形台底部
                [9, 10, 13], [10, 14, 13],  # 梯形台右面

                # 后面（整体后面）
                [2, 3, 6], [3, 7, 6],  # 长方体后面
                [6, 7, 10], [7, 11, 10],  # 长方体顶部到梯形台底部
                [10, 11, 14], [11, 15, 14],  # 梯形台后面

                # 左面（整体左面）
                [3, 0, 7], [0, 4, 7],  # 长方体左面
                [7, 4, 11], [4, 8, 11],  # 长方体顶部到梯形台底部
                [11, 8, 15], [8, 12, 15],  # 梯形台左面

                # 顶面（梯形台顶面）
                [12, 13, 14], [12, 14, 15]
            ])
            print(f"   创建了 {len(faces)} 个面片")

            print("\n4. 开始创建三角网格...")
            # 1. 首先创建完整的立体几何模型
            mesh = trimesh.Trimesh(vertices=vertices, faces=faces)
            print("   三角网格创建成功")

            print("\n5. 开始修正网格...")
            # 2. 修正法线方向并验证网格
            mesh.fix_normals()
            print("   法线方向已修正")
            mesh.process(validate=True)
            print("   网格已处理")
            mesh.merge_vertices(merge_tex=True)
            print("   重复顶点已合并")
            mesh.update_faces(mesh.unique_faces())
            print("   重复面片已移除")
            mesh.update_faces(mesh.nondegenerate_faces())
            print("   退化面片已移除")

            # 验证初始模型是否完整封闭
            if not mesh.is_watertight:
                print("   警告：初始几何模型可能不完全封闭")
            else:
                print("   模型检查通过：完全封闭")

            print("\n6. 准备生成四面体网格...")
            # 3. 准备 MeshPy 输入数据
            mesh_info = tet.MeshInfo()
            mesh_info.set_points(mesh.vertices.tolist())
            mesh_info.set_facets([f.tolist() for f in mesh.faces])
            print("   网格信息准备完成")

            print("\n7. 开始生成四面体网格...")
            try:
                # 使用更简单的网格生成选项
                opts = tet.Options(
                    switches='Q',  # Q: 安静模式
                    facesout=True,
                    edgesout=True,
                    neighout=True,
                    maxvolume=50.0,  # 显著增大体积限制
                    quiet=1  # 减少输出
                )
                print("   正在生成四面体网格...")

                # 不使用signal模块，直接尝试生成网格
                tet_mesh = tet.build(mesh_info, opts)
                print("   四面体网格生成成功！")
                print(f"   生成了 {len(tet_mesh.points)} 个节点")
                print(f"   生成了 {len(tet_mesh.elements)} 个四面体单元")

            except Exception as e:
                print(f"\n   四面体网格生成失败: {str(e)}")
                print("   仅返回表面三角网格信息...")

                # 评估网格质量
                try:
                    evaluate_mesh_quality(mesh)
                except Exception as quality_error:
                    print(f"   网格质量评估失败: {str(quality_error)}")

                # 返回表面网格的信息
                volume = mesh.volume
                area = C * width
                print(f"\n计算结果：")
                print(f"填筑体积: {volume:.2f} m³")
                print(f"征地面积: {area:.2f} m²")

                # 返回
                return mesh, volume, area

            # 四面体网格成功
            print("\n生成的网格信息：")
            print(f"顶点数量: {len(tet_mesh.points)}")
            print(f"四面体单元数量: {len(tet_mesh.elements)}")
            print(f"表面三角形数量: {len(tet_mesh.faces)}")
            print(f"边数量: {len(tet_mesh.edges)}")

            # 评估网格质量
            try:
                evaluate_mesh_quality(mesh)
            except Exception as quality_error:
                print(f"   网格质量评估失败: {str(quality_error)}")

            # 计算体积和面积
            volume = mesh.volume
            land_area = C * width
            return mesh, volume, land_area

        except Exception as e:
            raise Exception(f"创建网格时发生错误: {str(e)}")